import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;





public class Atmosphere {
	GL gl;
	GLU glu;
	static int SKY_SIZE = 5000; 
	public static Vector3D sun;
	private float longitude, latitude;
	private int shaderprogram;
	private int vert_shader, frag_shader;
	private float FPS;
	public static float pi = 3.1415f;
	
	public Vector3D getSun(){
		return sun;
	}
	
	public Atmosphere(GL gl_, GLU glu_){
		gl=gl_;
		glu=glu_;
		init();
		loadShader();
	}
	private void sun_init() {
		sun.setX(2000f);
		sun.setY(0f);
		sun.setZ(0f);
	}
	private void init(){
		sun = new Vector3D();
		sun.setX(2000f);
		sun.setY(0f);
		sun.setZ(0f);
		longitude = 20f*pi/180f;
		latitude = -30f*pi/180f;
		FPS = 1;
	}
	
	public void draw(Camera player, float fps){
		FPS = fps;
		sun_init();
		sun = sun_calc(player.pos);
		float x = player.pos.x();
	    float y = player.pos.y();
	    float z = player.pos.z();
	    gl.glDisable(GL.GL_CULL_FACE);
	    gl.glUseProgram(shaderprogram);
	    setShader(player);
	    gl.glColor3f(1f, 0f, 0f);
	    gl.glBegin(GL.GL_QUADS);
	    gl.glNormal3f(0f,0f,-1f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(0f,0f,-1f);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(0f,0f,-1f);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(0f,0f,-1f);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    //
	    gl.glNormal3f(-1f,0f,0f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(-1f,0f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(-1f,0f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(-1f,0f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    //
	    gl.glNormal3f(0f,1f,0f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(0f,1f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(0f,1f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(0f,1f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    //
	    gl.glNormal3f(0f,-1f,0f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(0f,-1f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(0f,-1f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(0f,-1f,0f);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);
	    //
	    gl.glNormal3f(1f,0f,0f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z+SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(1f,0f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(1f,0f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(1f,0f,0f);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z+SKY_SIZE);


	    gl.glNormal3f(0f,0f,1f);
	    gl.glTexCoord2d(0,1);
	    gl.glVertex3d(x+SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(0,0);
	    gl.glNormal3f(0f,0f,1f);
	    gl.glVertex3d(x-SKY_SIZE,y+SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,0);
	    gl.glNormal3f(0f,0f,1f);
	    gl.glVertex3d(x-SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);
	    gl.glTexCoord2d(1,1);
	    gl.glNormal3f(0f,0f,1f);
	    gl.glVertex3d(x+SKY_SIZE,y-SKY_SIZE,z-SKY_SIZE);

		gl.glEnd();
		gl.glUseProgram(0);
		gl.glEnable(GL.GL_CULL_FACE);
	}
	
	 
	 private void loadShader(){
		 vert_shader = gl.glCreateShader(GL.GL_VERTEX_SHADER);
	        frag_shader = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);
	        
	        BufferedReader brv = null;
			try {
				brv = new BufferedReader(
						new FileReader(
								"src/atmosphere.vert"));
			} catch (FileNotFoundException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
	        String vsrc = "";
	        String line;
	        try {
				while ((line=brv.readLine()) != null) {
				  vsrc += line + "\n";
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        gl.glShaderSource(vert_shader, 1,
	        		new String[] {vsrc}, (int[])null, 0);
	        gl.glCompileShader(vert_shader);
	        
	        BufferedReader brf = null;
			try {
				brf = new BufferedReader(
						new FileReader(
								"src/atmosphere.frag"));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        String fsrc = "";
	        String lines;
	        try {
				while ((lines=brf.readLine()) != null) {
				  fsrc += lines + "\n";
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        gl.glShaderSource(frag_shader, 1,
	        		new String[] {fsrc}, (int[])null, 0);
	        gl.glCompileShader(frag_shader);
	        
	        shaderprogram = gl.glCreateProgram();
	        gl.glAttachShader(shaderprogram, vert_shader);
	        gl.glAttachShader(shaderprogram, frag_shader);
	        gl.glLinkProgram(shaderprogram);
	        gl.glValidateProgram(shaderprogram);
	 }
	 private void setShader(Camera player){
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "poz"), player.pos.z());
	        gl.glUniform3f(gl.glGetUniformLocation(
	        		shaderprogram, "pozit"), player.pos.x()
	        		, player.pos.y(), player.pos.z());
	        gl.glUniform3f(gl.glGetUniformLocation(
	        		shaderprogram, "sunz"), sun.x(), sun.y(), sun.z());
	 }
	 private Vector3D sun_calc(Vector3D player) {
		 if(FPS < 1) FPS = 1; 
		longitude += 0;//(0.1f*pi/180)/FPS;
	    Vector3D sun1 = new Vector3D();
	    float angle = 0f;
	    Matrix4x4 matx = new Matrix4x4();
	    matx = Matrix4x4.set(1,0,0,0,
	             0,(float)Math.cos(latitude),(float)-Math.sin(latitude),0,
                 0,(float)Math.sin(latitude),(float)Math.cos(latitude),0,
	             0,0,0,1);
	    Matrix4x4 maty = new Matrix4x4();
	    maty = Matrix4x4.set((float)Math.cos(longitude),0,(float)Math.sin(longitude),0,
	                   0,1,0,0,
	                   (float)-Math.sin(longitude),0,(float)Math.cos(longitude),0,
	                   0,0,0,1);
	    
	    Matrix4x4 matz = new Matrix4x4();
	    matz = Matrix4x4.set((float)Math.cos(angle),(float)-Math.sin(angle),0,0,
	    		(float)Math.sin(angle),(float)Math.cos(angle),0,0,
	                   0,0,1,0,
	                   0,0,0,1);
	    sun1 = Matrix4x4.mult(Matrix4x4.mult(Matrix4x4.mult(matx,maty),matz),sun);
	    return sun1;
	}
}